import socket

from utils import logging
from protocol import Protocol, FILE_MESSAGE, JSON_MESSAGE, TEXT_MESSAGE
from buff import Buff


class BaseHandler(object):

    def __init__(self, sock: socket.socket, address: tuple, parent):

        logging.info("连接成功 {}:{}".format(address[0], address[1]))

        self.__socket = sock
        self.__buff = Buff(sock)
        self.remote_address = address
        self.parent = parent

        self.is_connection = True

    @property
    def buff(self):
        return self.__buff

    def on_message(self, request: Protocol):
        """
        有信息来的回调函数

        :param request:
        :return:
        """

        if self.before_request_middleware(request):
            self.handle(request)

    def on_connect_err(self, err_type: str, descriotion: str):
        """
        链接发生错误

        :param err_type:
        :param descriotion:
        :return:
        """
        logging.info(descriotion)
        self.close_connnect()

    def handle(self, request: Protocol):
        """
        处理信息方法, 自己继承重写

        :param request:
        :return:
        """

        if request.type == FILE_MESSAGE:
            self.file_handler(request)
        elif request.type == TEXT_MESSAGE:
            self.text_handler(request)
        elif request.type == JSON_MESSAGE:
            self.json_handler(request)

    def file_handler(self, request: Protocol):
        raise ReferenceError("文件信息处理方法, 自己继承重写")

    def text_handler(self, request: Protocol):
        raise ReferenceError("文本信息处理方法, 自己继承重写")

    def json_handler(self, request: Protocol):
        raise ReferenceError("JSON信息处理方法, 自己继承重写")

    def before_request_middleware(self, request: Protocol) -> bool:
        """
        请求前执行的中间件

        :param request:
        :return:
        """

        raise ReferenceError("请求前执行的中间件, 需继承重写")

    def send(self, protocol: Protocol):
        self.buff.write(protocol.raw, encdoe=False)
        self.buff.send()

    def close_connnect(self):
        self.is_connection = False

        self.parent.node_disconnection(self.remote_address)

        try:
            self.__socket.close()
        except Exception:
            pass
